#include <netinet/in.h>
#include <string.h>
#include <regex>
#include <iostream>

#include "base.hpp"
// ====================================================================================================
size_t   rudp::sock_slice = 0;                    // 数据分片长度
uint16_t rudp::m_send_id  = 0;                    // 发送ID

const int rudp::EXP_ARRAY[ 10 ] = { 1 , 2 , 7 ,20 , 54 , 148 , 403 , 1096 , 8103 , 8103 };
	/* 斐波那契数列退避索引表 */
const int rudp::FIB_ARRAY[ 10 ] = { 1 , 1 , 2 ,3 ,  5  , 8 ,   13 ,  21 ,34 , 55 };
// ====================================================================================================
void on_rudp_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags )
{
	if( handle == nullptr ) return;
	if( buf == nullptr ) return;
	if( addr == nullptr ) return;

	rudp * p_obj = (rudp*)(handle->data);

	if( p_obj ){
		p_obj->on_raw_recv( buf->base , nread , addr );
	}
	if( buf->base != nullptr )
		free( buf->base );
}

void on_rudp_send(uv_udp_send_t* req, int status)
{
	if( req == nullptr ) return;
	if( status ){
	        rudp::sendreq  * sreq = (rudp::sendreq*)req->data;
		rudp * obj = nullptr;
		if( sreq ){
		        rudp::rudp_pkge_t * pkg = nullptr;
			obj = sreq->obj;
			rudp::unpacket( sreq->buf->base , sreq->buf->len , &pkg );
			obj -> on_raw_send( pkg );
			delete pkg;
			delete sreq;
		}
	}
}

void on_rdup_alloc( uv_handle_t* handle, unsigned int s , uv_buf_t* buf)
{
	if( handle == nullptr ) return;
	rudp * obj = (rudp*)handle->data;

	if( obj ){
		buf->base = ( char *)malloc( s );
		size_t l = s;
		if( buf->base == nullptr ){
			buf->base = ( char*)malloc( s >> 1 );
			l = l >> 1;
		}

		if( buf->base ){
			buf->len = l;
		}
	}
}

void on_rudp_getaddrinfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
{
      if( req == nullptr ) return;
      rudp * obj = ( rudp*)(req->data);
      if( obj == nullptr ) return;
      
      if( status == 0 )
	   obj->on_resolve( res );
      else
	   obj->on_resolve( nullptr );
}


////////////////////////////////////////////////////////////////////////////////////////////////////
rudp :: stprotocol :: stprotocol()
{
	msg_id         = 0;
	start_id       = 0;
	qos_ip.qos     = 0;
	qos_ip.ip_type = 0;
	opt            = 0;
	len            = 0;
	pkg_count      = 0;
	data           = nullptr;
	next           = nullptr;
	escape_cur     = 0;
}

rudp :: stprotocol :: stprotocol( uint16_t id , uint16_t opt , uint8_t qos )
{
	msg_id         = id;
	start_id       = id;
	qos_ip.qos     = ( qos & 0x03 );
	qos_ip.ip_type = 0;
	len            = 0;
	opt            = opt;
	pkg_count      = 1;
	data           = nullptr;
	next           = nullptr;
	escape_cur     = 0;
}

rudp :: stprotocol :: stprotocol( uint16_t id , uint16_t _opt , uint8_t _qos , int _len , unsigned char * __data )
{
	msg_id         = id;
	start_id       = id;
	qos_ip.qos     = ( _qos & 0x03 );
	qos_ip.ip_type = 0;
	len            = _len;
	opt            = _opt;
	pkg_count      = 1;
	data           = (unsigned char *)malloc( len );
	if( data != nullptr ){
		memcpy( data , __data , len );
	}
	else throw rudp::ERR_ALLOC_MEM; 
	next           = nullptr;
	escape_cur     = 0;
}

rudp :: stprotocol :: ~stprotocol()
{
	if( data ) free( data );
}

int rudp :: stprotocol :: operator()( char ** data )
{
      if( * data == nullptr )
            * data = ( char *)malloc( len );
      if( * data == nullptr ){
	    return (int)(rudp::ERR_ALLOC_MEM);
      }
      memcpy( * data , this->data , len );
      return len;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
rudp :: stprotocol_buff :: stprotocol_buff()
{
	count = 0;
}

rudp :: stprotocol_buff :: ~stprotocol_buff()
{
}

int rudp :: stprotocol_buff :: get( char ** __data )
{
        int len = 0 , ret , start;
	char * d = nullptr;
	std::map< uint16_t , rudp_pkge_t*>::iterator it;
	
	it = data.begin();
	start = it->second->start_id;

	for( size_t i = start; i < start + count; i ++ ){
		it = data.find( i );
		if( d == nullptr ){
			d = ( char *) malloc( it->second -> len );
			if( d != nullptr ){
				memcpy( d ,it->second->data , it->second->len );
				len += it->second->len;
			}
		}else{
			d = (char *)realloc( d , len + it->second->len + len );
			if( d ){
				memcpy( d + len , it->second->data , it->second->len );
				len += it->second->len;
			}
		}

		if( d == nullptr )
			ret = (int)( rudp::ERR_ALLOC_MEM );
	}

	if( d ){
		*__data = d;
		ret = len;
	}else{
		__data = nullptr;
	}
	
	return ret;
}

void rudp :: stprotocol_buff :: insert( rudp:: rudp_pkge_t * pkg )
{
	if( pkg == nullptr ) return;
	
	data.insert( std::pair< uint16_t , rudp_pkge_t * >( pkg->msg_id , pkg ) );
}

void rudp :: stprotocol_buff :: clear()
{
        for( std::map< uint16_t , rudp_pkge_t* >::iterator it = data.begin();  it != data.end(); it ++ ){
		if( it->second ) delete it->second;
	}

	data.erase( data.begin() , data.end() );
	count = 0;
}

size_t rudp :: stprotocol_buff :: size()
{
	return data.size();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
rudp::sendreq :: sendreq( size_t s , const char * data , rudp * __obj )
{
	buf = (uv_buf_t*)malloc( sizeof( uv_buf_t ));
	if( data == nullptr ){
		throw ERR_DATA_NULL;
	}
	if( obj == nullptr ){
		throw ERR_OBJ_NULL;
	}
	else{
		obj = __obj;
	}
	
	if( buf ){
		buf->base = ( char *)malloc( s );
		if( buf->base ){
			memcpy( buf->base , data , s );
		}
		else{
			throw ERR_ALLOC_MEM;
		}
	}else{
		throw ERR_ALLOC_MEM;
	}
}
rudp ::sendreq :: ~sendreq()
{
	if( buf && buf->base ){
		free( buf->base );
		free( buf );
	}
}
////////////////////////////////////////////////////////////////////////////////////////////////////

void rudp :: on_raw_recv( const char * data , size_t len , const struct sockaddr * peer )
{
	rudp_pkge_t  * package = nullptr;
	unpacket( data , len , &package );
	if( package ){
		// 检查是否是反馈包
		if( package->msg_id & 0x1 ){ // 是发送包 ， 根据操作类型进行分别处理
			switch( package->opt ){
			case SEND:
				do_on_send( package , peer );
				break;
			case KEEPALIVE:
				do_on_keepalive( package );
				break;
			case PING:
				do_on_ping( package );
				break;
			case CONNECT:
				do_on_connect( package , peer ); 
				break;
			case CLOSE:
				do_on_close( package , peer );
				break;
			default:
				break;
			}
		}else{// 是反馈包， 检查是否有对应的发出数据包，如果有对应的数据包则进行相应的处理
			switch( package->opt ){
			case SEND_E:
				do_on_send_echo( package );
				break;
			case KEEPALIVE_E:
				do_on_keepalive_echo( package );
				break;
			case PING_E:
			        do_on_ping_echo( package );
				break;
			case CONNECT_E:
			        do_on_connect_echo( package , peer );
				break;
				//case CONNECT_EE:
				//do_on_connect_echo_echo( package , peer );
				//break;
			case CLOSE_E:
			        do_on_close_echo( package , peer );
				break;
			default:break;
			}
		}
	}
}

void rudp :: resolver( const std::string& url , int port , std::function< void( const struct addrinfo* cb )> fun )
{
	std::stringstream ss;
	ss << port;
	std::string port_str = ss.str();

	struct addrinfo hints;
	uv_getaddrinfo_t * req = ( uv_getaddrinfo_t*)malloc( sizeof( uv_getaddrinfo_t ) );
	req->data = this;
	if( req ){
		// 设置回调函数
		on_resolv_cb = fun;
		// 配置解析线索
		hints.ai_family   = AF_INET;
		hints.ai_protocol = 0;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_flags    = 0;
		int e = uv_getaddrinfo( p_loop , req , on_rudp_getaddrinfo , url.c_str() , port_str.c_str() , &hints );
		if( e ){
			throw ERR_UV_DNS_RESOLVE;
		}
	}else{
		throw ERR_ALLOC_MEM;
	}
}

void rudp :: on_resolve( struct addrinfo * info )
{
	if( info && !on_resolv_cb ){
		struct sockaddr * p = nullptr;

		do{
			p = info->ai_addr;
			memcpy( &peer , p , sizeof( struct sockaddr ) );
			real_connect();
			// 等候连接成功，或者超时
			while( m_status == STATUS_CONNECT_1 || m_status == STATUS_READY || m_status == STATUS_CONNECT_2 );
			if( m_status == STATUS_OVERTIME ){
				std::cerr << "server is down" << std::endl;
				m_status = STATUS_READY;
				// 连接失败，尝试连接下一个服务器
				info = info->ai_next;
			}else if( m_status == STATUS_CONNECTED ){
				// 成功建立连接
				// TODO: 添加相关代码
				// 如果开启了KEEPALIVE， 则启动对应的计时器

				// 获取系统支持数据包分包长度
				int fd;
				int e = uv_fileno( (uv_handle_t*)&m_udp , &fd );
				if( e == 0 ){
					socklen_t l;
					e = getsockopt( fd , SOL_SOCKET , SO_SNDBUF ,  &sock_slice , &l );
					if( e ){  // 发送错误
					}
				}else{ // 发生错误
				}
				break;       // 
			}
		}while( info != nullptr );
		if( info == nullptr ){
			std::cerr << "server is down" << std::endl;
			m_status = STATUS_READY;
		}
	}else if( on_resolv_cb ){
		on_resolv_cb( info );
	}
}


void rudp :: resolver( const std::string& url , int port )
{
	std::stringstream ss;
	ss << port;
	std::string port_str = ss.str();

	struct addrinfo hints;
	uv_getaddrinfo_t * req = ( uv_getaddrinfo_t*)malloc( sizeof( uv_getaddrinfo_t ) );
	req->data = this;
	if( req ){
		hints.ai_family   = AF_INET;
		hints.ai_protocol = 0;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_flags    = 0;
		int e = uv_getaddrinfo( p_loop , req , on_rudp_getaddrinfo , url.c_str() , port_str.c_str() , &hints );
		if( e ){
			// TODO: 添加错误处理代码
		}
	}else{
		// 内存分配失败
	}
}

void rudp :: on_raw_send( rudp_pkge_t * package )
{
	if( package )
		do_on_finish_send( package );
}

void rudp :: raw_send( const char * data , size_t len )
{
	uv_udp_send_t * req = ( uv_udp_send_t*)malloc( sizeof( uv_udp_send_t ));
	if( req ){
		try{
			req -> data = new sendreq( len , data , this );

			int e = uv_udp_send( req , &m_udp , ((sendreq*)req->data)->buf , 1 , &peer , on_rudp_send );
			if( e ){// udp发送错误
				throw ERR_UV_UDP_SEND;
			}
		}catch( std::bad_alloc& e ){
			
		}catch( err_code e ){
		}
	}else{// 内存分配失败
		// TODO 添加错误处理
	}
}

void rudp :: packet( const char * data , size_t len , rudp_pkge_t ** pkge )
{
        int count = 0 , size = sock_slice - sizeof( rudp_pkge_t );
        size_t packed = 0;
	uint16_t  start_id = m_send_id;
	rudp_pkge_t * tmp_next = nullptr;
	if( len > sock_slice ){   // 如果数据的长度大于数据的分包长度，则应该将数据分成多包发送
		count = len % size + 1;
	}
	try{
		if( count > 1 ){
		  *pkge = new rudp_pkge_t( m_send_id , SEND , QOS3 , size , (unsigned char *)data );
			packed += size;
		}
		else{
		  *pkge = new rudp_pkge_t( m_send_id , SEND , QOS3 , len , (unsigned char *)data );
			packed += len;
		}

		tmp_next = *pkge;
		tmp_next-> start_id = start_id;
		tmp_next-> pkg_count = (uint16_t)count;
		m_send_id += 2;
		
		for( int i = 1; i < count; i ++ ){
			rudp_pkge_t * tmp = nullptr;
			if( packed + size > len ){
			        tmp = new rudp_pkge_t( m_send_id , SEND , QOS3 , len - packed , (unsigned char *)(data + packed ));
				packed += len - packed;
			}else{
			        tmp = new rudp_pkge_t( m_send_id , SEND , QOS3 , size , (unsigned char *)(data + packed ));
				packed += size;
			}

			tmp_next->next = tmp;
			tmp_next = tmp;
			tmp_next-> start_id = start_id;
			tmp_next-> pkg_count = (uint16_t) count;
			m_send_id += 2;
		}
	}catch( std::bad_alloc& e ){
		// 内存分配失败
	}catch( err_code e ){
		
	}
}

void rudp :: packet_e( const rudp_pkge_t * pkgein , rudp_pkge_t ** pkgeout )
{
	if( pkgein == nullptr ){
		*pkgeout = nullptr;
		return;
	}
	
	try{
		*pkgeout = new rudp_pkge_t( pkgein->msg_id + 1 , SEND_E , QOS5 );
	}catch( std::bad_alloc& e ){
		// 内存分配失败
		*pkgeout = nullptr;
	}
	catch( err_code e ){
	}
}
	
void rudp :: packet_ping( rudp_pkge_t ** pkge )
{
	try{
		*pkge = new rudp_pkge_t( m_send_id , PING , QOS1 );
		m_send_id += 2;
	}catch( std::bad_alloc& e ){
		
	}catch( err_code e ){
	}
}

void rudp :: packet_ping_e( const rudp_pkge_t * pkgein , rudp_pkge_t ** pkgeout )
{
	try{
		*pkgeout = new rudp_pkge_t( pkgein->msg_id + 1 , PING_E , QOS5 );
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}
	
void rudp :: packet_connect( rudp_pkge_t **pkge )
{
	try{
		*pkge = new rudp_pkge_t( m_send_id , CONNECT , QOS4 );
		m_send_id += 2;
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}

void rudp :: packet_connect_e( const rudp_pkge_t * pkgein , rudp_pkge_t ** pkgeout )
{
	try{
		*pkgeout = new rudp_pkge_t( pkgein->msg_id + 1 , CONNECT_E , QOS4 );
		m_send_id += 2;
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}


void rudp :: packet_close( rudp_pkge_t ** pkge )
{
	try{
		*pkge = new rudp_pkge_t( m_send_id , CLOSE , QOS4 );

		m_send_id += 2;
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}

void rudp :: packet_close_e( const rudp_pkge_t * pkgein , rudp_pkge_t ** pkgeout )
{
	try{
		*pkgeout = new rudp_pkge_t( pkgein->msg_id + 1 , CLOSE_E , QOS5 );
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}

void rudp :: packet_keepalive( rudp_pkge_t ** pkge )
{
	try{
		/// @note RUDP的保活机制有两个目的，第一是保持数据链路的保持；而是保持两个
		/// 端点确认有效。因此发送数据需要接收端有一个响应。但是如果发送端数据在一定
		/// 时间内没有发现有发现响应则说明链路无效；同样的对应接收端来说，如果再一定
		/// 时间内没有接收到的包活操作的数据，则说明客户端连接失效
	        *pkge = new rudp_pkge_t( m_send_id , KEEPALIVE , QOS1 );
	}catch( std::bad_alloc& e ){
	}catch( err_code e ){
	}
}
void rudp :: packet_keepalive_e( const rudp_pkge_t *pkgein , rudp_pkge_t ** pkgeout )
{
	try{
		*pkgeout = new rudp_pkge_t( pkgein->msg_id + 1 , KEEPALIVE_E , QOS5 );
		
	}catch( std::bad_alloc& e ){
		*pkgeout = nullptr;
	}catch( err_code e ){
		*pkgeout = nullptr;
	}
}

void rudp :: unpacket( const char * data , size_t len , rudp_pkge_t ** pkge )
{
	try{
		*pkge = new rudp_pkge_t( );
		if( len >= 12 ){
			memcpy( (void*)pkge , data , 12 );
			if( (*pkge)->len > 0 ){// 包含有载荷数据
			        (*pkge) -> data = ( unsigned char *)malloc( (*pkge)->len );
				if( (*pkge) -> data != nullptr ){
				     memcpy( (*pkge)->data , data + 12 , len - 12 );
				}
			}
		}
		else{// 数据包不完整
			// TODO ,添加错误处理代码
		}
	}catch( std::bad_alloc& e ){
		*pkge = nullptr;
	}catch( err_code e ){
		*pkge = nullptr;
	}
}

void rudp :: do_on_finish_send( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;
	switch( pkge -> qos_ip.qos ){
	case QOS0:	break;
	case QOS1:
		m_waiting_echo.insert( std::pair< uint32_t , rudp_pkge_t*>( pkge->msg_id , pkge ) );
		// 设置计时器操作
		pkge->retreat_timer( DEFAULT_ABORT_TICK );
		pkge->retreat_timer.SetOwner( [this , pkge ](){// 如果再一定时间内没有接受到响应则放弃接收响应。
		      // 删除记录
		      std::map< uint32_t , rudp_pkge_t *>::iterator it;
			it = m_waiting_echo.find( pkge->msg_id );
			if( it != m_waiting_echo.end() )
				m_waiting_echo.erase( it );
		});
		// 启动计时器
		pkge->retreat_timer.Start( -1 , true );
		break;
	case QOS2:// 连续重发操作，直到接收到响应
		if( m_waiting_echo.find( pkge->msg_id ) == m_waiting_echo.end() )
			m_waiting_echo.insert( std::pair< uint32_t , rudp_pkge_t*>( pkge->msg_id , pkge ) );

		pkge->retreat_timer.SetOwner( [ this , pkge ]{
			char * data = nullptr;
			int len = 0;
			len = (*pkge)(&data);
			
			if( len > 0 ){
				raw_send( data , len );
			}
				
			if( data ) free( data );

		});

		pkge->retreat_timer.Start( 50 , true );
		break;
	case QOS3:
		if( m_waiting_echo.find( pkge->msg_id ) == m_waiting_echo.end() ){
			m_waiting_echo.insert( std::pair< uint32_t , rudp_pkge_t*>( pkge->msg_id , pkge ));
		}
		pkge->retreat_timer( EXP_ARRAY[ pkge->escape_cur ] );
		pkge->escape_cur ++;

		pkge->retreat_timer.SetOwner([ this , pkge]{
				// 发送数据
				char * data = nullptr;
				int len;
				len = (*pkge)( & data );
				if( len > 0 ){
					raw_send( data , len );
				}
				free( data );
				// 如果已经达到最大间隔，则放弃重发
				if( pkge->escape_cur >= 10 ){
					std::map< uint32_t , rudp_pkge_t *>::iterator it = m_waiting_echo.find( pkge->msg_id );
					if( it != m_waiting_echo.end() ){
						m_waiting_echo.erase( it );
					}
				}
			});

		pkge->retreat_timer.Start( -1 , true );
		break;
	case QOS4:
		if( m_waiting_echo.find( pkge->msg_id ) == m_waiting_echo.end() ){
			m_waiting_echo.insert( std::pair< uint32_t , rudp_pkge_t*>( pkge->msg_id , pkge ));
		}
		pkge->retreat_timer( FIB_ARRAY[ pkge->escape_cur ] );
		pkge->escape_cur ++;

		pkge->retreat_timer.SetOwner([ this , pkge]{
				// 发送数据
				char * data = nullptr;
				int len;
				len = (*pkge)( & data );
				if( len > 0 ){
					raw_send( data , len );
				}
				free( data );
				// 如果已经达到最大间隔，则放弃重发
				if( pkge->escape_cur >= 10 ){
					std::map< uint32_t , rudp_pkge_t *>::iterator it = m_waiting_echo.find( pkge->msg_id );
					if( it != m_waiting_echo.end() ){
						m_waiting_echo.erase( it );
					}
				}
			});

		break;
	case QOS5:
		if( m_waiting_echo.find( pkge->msg_id ) == m_waiting_echo.end() ){
			m_waiting_echo.insert( std::pair< uint32_t , rudp_pkge_t*>( pkge->msg_id , pkge ));
		}
		pkge->retreat_timer( 20 );
		pkge->escape_cur ++;

		pkge->retreat_timer.SetOwner([ this , pkge]{
				// 发送数据
				char * data = nullptr;
				int len;
				len = (*pkge)( & data );
				if( len > 0 ){
					raw_send( data , len );
				}
				free( data );
				// 如果已经达到最大间隔，则放弃重发
				if( pkge->escape_cur >= 5 ){
					std::map< uint32_t , rudp_pkge_t *>::iterator it = m_waiting_echo.find( pkge->msg_id );
					if( it != m_waiting_echo.end() ){
						m_waiting_echo.erase( it );
					}
				}
			});

		break;
	default:break;
	}
}

void rudp :: send_packet( rudp_pkge_t * p )
{
	int len = 0;
	char * data;

	if( p == nullptr ) return;

	len = (*p)( &data );
	if( len > 0 ){
		raw_send( data , len );
	}

	delete p;  // 释放数据包
}



void rudp :: do_on_send_echo( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;

	// 查找等候响应数据HASH表
	std::map< uint32_t , rudp_pkge_t * >::iterator it;
	it = m_waiting_echo.find( pkge->msg_id - 1 );
	if( it != m_waiting_echo.end() ){
		if( it->second ){
			it->second->retreat_timer.Stop();
			delete it->second;
		}
		m_waiting_echo.erase( it );
	}
}

void rudp :: do_on_keepalive( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;
	if( is_keepalive_e == false ) return;    // 没有开启包活响应

	rudp_pkge_t * pkg = nullptr;

	packet_keepalive_e( pkge , &pkg );
	if( pkg )
		send_packet( pkg );
}

void rudp :: do_on_keepalive_echo( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;

	std::map< uint32_t , rudp_pkge_t * >::iterator it;
	it = m_waiting_echo.find( pkge->msg_id );
	if( it != m_waiting_echo.end() ){
		if( it->second )
			delete it->second;
		m_waiting_echo.erase( it );
	}
}

void rudp :: do_on_ping( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;
	if( ping_e == false ) return;  // 如果没有开启PING响应，立即返回
	// 构造PING反馈包
	rudp_pkge_t * pkg = nullptr;

	packet_ping_e( pkge , &pkg );

	// 发送PING反馈宝
	if( pkg )
		send_packet( pkg );
}

void rudp :: do_on_ping_echo( rudp_pkge_t * pkge )
{
	if( pkge == nullptr ) return;

	std::map< uint32_t , rudp_pkge_t * > ::iterator it;
	it = m_waiting_echo.find( pkge->msg_id -1 );
	if( it != m_waiting_echo.end() ){
		if( it->second ) {
			it->second->retreat_timer.Stop();
			delete it->second;
		}
		m_waiting_echo.erase( it );
	}
}

rudp :: rudp()
{
        sock_slice = 0;
	m_error = OK;
	try{
		init_uv();
	}catch( err_code e ){
		throw ERR_INIT_UV;
	}
}

rudp :: rudp( int p )
{
	port = p;
	init_uv();
	sock_slice = 0;
	uv_ip4_addr( "0.0.0.0" , p , (struct sockaddr_in*)&peer );
	uv_udp_bind( &m_udp , &peer ,  UV_UDP_REUSEADDR );
}

rudp::rudp( const std::string& _url , int _port )
{
	m_error   = OK;
	url       = _url;
	port      = _port;
	m_send_id = 0;
	sock_slice = 0;
	try{
		init_uv();
		if( p_loop != nullptr ){
			std::regex reg( "[12]\\d{0,2}(\\.[12]\\d{0,2}){3}" );
			if( std::regex_match( url , reg ) == true ){
				struct sockaddr_in  add;
				add.sin_family      = AF_INET;
				add.sin_port        = port;
				add.sin_addr.s_addr = inet_addr( url.c_str() );
				memset( add.sin_zero , 0 , 8 );

				memcpy( &peer , &add , sizeof( add ) );

				uv_udp_recv_start( &m_udp , on_rdup_alloc , on_rudp_recv );
				real_connect();
			}else{
				resolver( url , port );
			}
		}else{
			throw ERR_INIT_UV;
		}
	}catch( err_code e ){
		throw ERR_INIT_UV;
	}
}

void rudp :: real_connect()
{
      rudp_pkge_t * pkg = nullptr;
      packet_connect( &pkg );
      if( pkg ){
	    send_packet( pkg );
      }
}

/*
rudp :: ~rudp()
{
	m_error = OK;
	
	uv_udp_recv_stop( &m_udp );
	if( p_loop ){
		uv_loop_close( p_loop );
	}

	if( close_cb )
		close_cb( m_error );
}
*/
void rudp::init_uv()
{
	p_loop = uv_default_loop();
	if( p_loop ){
  	        int e = uv_udp_init( p_loop , &m_udp );
		if( e ){
			uv_loop_close( p_loop );
			p_loop = nullptr;
			std::cerr << "Init udp handle fail" << std::endl;
			throw ERR_INIT_UDP;
		}
	}else{
	     throw ERR_INIT_UV_LOOP;
	}
	
}

rudp :: err_code
rudp :: connect( const std::string& _url , int _port )
{
	m_error   = OK;
	url       = _url;
	port      = _port;
	
	try{
		if( p_loop != nullptr ){
			std::regex reg( "[012]\\d{0,2}(\\.[012]\\d{0,2}){3}" );
			if( std::regex_match( url , reg ) == true ){
				struct sockaddr_in  add;
				add.sin_family        = AF_INET;
				add.sin_port          = port;
				add.sin_addr.s_addr   = inet_addr( url.c_str() );
				memset( add.sin_zero , 0 , 8 );

				memcpy( &peer , &add , sizeof( add ) );

				uv_udp_recv_start( &m_udp , on_rdup_alloc , on_rudp_recv );
				real_connect();
			}else{
				resolver( url , port );
			}
		}else{
			m_error =  ERR_INIT_UV;
		}
	}catch( err_code e ){
		m_error = ERR_INIT_UV;
	}

	return m_error;
}

rudp::err_code rudp :: close()
{
	delete this;
	return m_error;
}

rudp :: err_code
rudp :: evt_close( std::function<void(err_code)> cb )
{
	close_cb = cb;
	m_error = OK;
	return m_error;
}

rudp :: err_code
rudp :: evt_connected( std::function< void ( err_code )> cb )
{
	connect_cb = cb;
	return OK;
}

rudp :: err_code
rudp :: send( const char * data , size_t len )
{
	rudp_pkge_t * pkg = nullptr;
	packet( data , len , &pkg );

	while( pkg ){
		send_packet( pkg );
		pkg = pkg->next;
	}

	return m_error;
}

void rudp :: onsend( std::function<void ( err_code ) > cb )
{
	send_cb = cb;
}

rudp :: err_code
rudp :: evt_recv( std::function<void ( const char * , size_t , err_code )> cb )
{
	recv_cb = cb;
	return OK;
}

void rudp :: keepalive( bool sw , long intval )
{
	if( sw ){
		is_keepalive = sw;
		keepalive_intval = intval;

		keep_alive_timer.SetOwner( [this]{
				rudp_pkge_t * pkg = nullptr;
				if( pkg )
					send_packet( pkg );

				keep_alive_timer.Start( -1 , true );
			});
		keep_alive_timer( intval );
		keep_alive_timer.Start( -1 , true );
	}else{
		keep_alive_timer.Stop();
	}
}

rudp :: err_code
rudp :: ping( int intval , int count  )
{
	ping_count = count;
	ping_intval = intval;

	ping_timer( intval );
	ping_timer.SetOwner( [ this ]{
			rudp_pkge_t * pkg = nullptr;
			packet_ping( &pkg );
			if( pkg ){
				send_packet( pkg );
				if( ping_count == -1 ){
					ping_timer.Start( -1 , true );
				}else if( ping_count > 1 ){
					ping_count --;
					ping_timer.Start( -1 , true );
				}
			}
		});

	ping_timer.Start( -1 , true );

	return m_error;
}

rudp :: err_code
rudp :: evt_ping( std::function< void ( err_code )> cb )
{
	ping_cb = cb;
	return OK;
}

void rudp::connect( const std::string& url , int port , std::function< void (err_code) > cb )
{
      connect_cb = cb;
      connect( url , port );
}
